package org.qh.common.mq.config;

import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.qh.common.mq.properties.MqProperties;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;

import java.util.HashMap;
import java.util.Map;

@Slf4j
@AutoConfiguration
@ConditionalOnProperty(prefix = "mq", value = {"enabled"}, havingValue = "true", matchIfMissing = true)
@EnableConfigurationProperties(MqProperties.class)
public class DeadLetterMQConfiguration {

    @PostConstruct
    private void init() {
        log.info("rabbitmq初始化成功！");
    }

    @Resource
    private MqProperties mqProperties;

    /**
     * 配置RabbitMQ连接工厂 - 只有当mq.enabled=true时才会创建
     */
    @Bean
    public ConnectionFactory connectionFactory() {
        CachingConnectionFactory connectionFactory = new CachingConnectionFactory();
        connectionFactory.setHost(mqProperties.getHost());
        connectionFactory.setPort(mqProperties.getPort());
        connectionFactory.setUsername(mqProperties.getUsername());
        connectionFactory.setPassword(mqProperties.getPassword());
        connectionFactory.setVirtualHost(mqProperties.getVirtualHost());
        return connectionFactory;
    }

    /**
     * RabbitAdmin - 管理RabbitMQ
     */
    @Bean
    public RabbitAdmin rabbitAdmin(ConnectionFactory connectionFactory) {
        return new RabbitAdmin(connectionFactory);
    }

    /**
     * RabbitTemplate - 发送消息
     */
    @Bean
    public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
        return new RabbitTemplate(connectionFactory);
    }

    /**
     * 监听器容器工厂
     */
    @Bean
    public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(ConnectionFactory connectionFactory) {
        SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory);
        return factory;
    }


    /**
     * 声明死信交换机
     */
    @Bean
    public DirectExchange dlxExchange() {
        return new DirectExchange(mqProperties.getDlxExchange());
    }

    /**
     * 声明死信队列
     */
    @Bean
    public Queue dlxQueue() {
        return new Queue(mqProperties.getDlxQueue());
    }

    /**
     * 声明订单业务交换机
     */
    @Bean
    public DirectExchange orderExchange() {
        return new DirectExchange(mqProperties.getOrderExchange());
    }

    /**
     * 声明订单队列 核心操作一
     */
    @Bean
    public Queue orderQueue() {
        Map<String, Object> arguments = new HashMap<>(2);
        // 绑定我们的死信交换机
        arguments.put("x-dead-letter-exchange", mqProperties.getDlxExchange());
        // 绑定我们的路由key
        arguments.put("x-dead-letter-routing-key", mqProperties.getDlxRoutingKey());
        return new Queue(mqProperties.getOrderQueue(), true, false, false, arguments);
    }

    /**
     * 绑定订单队列到订单交换机
     */
    @Bean
    public Binding orderBinding() {
        return BindingBuilder.bind(orderQueue()).to(orderExchange()).with(mqProperties.getOrderRoutingKey());
    }

    /**
     * 绑定死信队列到死信交换机
     */
    @Bean
    public Binding binding() {
        return BindingBuilder.bind(dlxQueue()).to(dlxExchange()).with(mqProperties.getDlxRoutingKey());
    }

    /**
     * 商品过期主交换机
     */
    @Bean
    public DirectExchange shopExpirationExchange() {
        return new DirectExchange(mqProperties.getCardExpirationExchange(), true, false);
    }

    /**
     * 商品过期主队列
     */
    @Bean
    public Queue shopExpirationQueue() {
        Map<String, Object> args = new HashMap<>(4);
        // 绑定专属死信交换机
        args.put("x-dead-letter-exchange", mqProperties.getCardExpirationDlx());
        // 绑定专属死信路由键
        args.put("x-dead-letter-routing-key", mqProperties.getCardExpirationDlRoutingKey());
        // 可选：设置队列消息的默认过期时间（毫秒）
        args.put("x-message-ttl", 86400000); // 24小时
        return new Queue(mqProperties.getCardExpirationQueue(), true, false, false, args);
    }

    /**
     * 绑定主队列到主交换机
     */
    @Bean
    public Binding shopExpirationBinding() {
        return BindingBuilder.bind(shopExpirationQueue())
            .to(shopExpirationExchange())
            .with(mqProperties.getCardExpirationRoutingKey());
    }

    /**
     * 商品专属死信交换机
     */
    @Bean
    public DirectExchange shopExpirationDLX() {
        return new DirectExchange(mqProperties.getCardExpirationDlx(), true, false);
    }

    /**
     * 商品专属死信队列
     */
    @Bean
    public Queue shopExpirationDLQ() {
        return new Queue(mqProperties.getCardExpirationDlq(), true);
    }

    /**
     * 绑定死信队列到死信交换机
     */
    @Bean
    public Binding shopExpirationDLBinding() {
        return BindingBuilder.bind(shopExpirationDLQ())
            .to(shopExpirationDLX())
            .with(mqProperties.getCardExpirationDlRoutingKey());
    }


    /**
     * 商品过期主交换机
     */
    @Bean
    public DirectExchange vipExpirationExchange() {
        return new DirectExchange(mqProperties.getVipExpirationExchange(), true, false);
    }

    /**
     * 商品过期主队列
     */
    @Bean
    public Queue vipExpirationQueue() {
        Map<String, Object> args = new HashMap<>(4);
        // 绑定专属死信交换机
        args.put("x-dead-letter-exchange", mqProperties.getVipExpirationDlx());
        // 绑定专属死信路由键
        args.put("x-dead-letter-routing-key", mqProperties.getVipExpirationDlRoutingKey());
        // 可选：设置队列消息的默认过期时间（毫秒）
        args.put("x-message-ttl", 86400000); // 24小时
        return new Queue(mqProperties.getVipExpirationQueue(), true, false, false, args);
    }

    /**
     * 绑定主队列到主交换机
     */
    @Bean
    public Binding vipExpirationBinding() {
        return BindingBuilder.bind(vipExpirationQueue())
            .to(vipExpirationExchange())
            .with(mqProperties.getVipExpirationRoutingKey());
    }

    /**
     * 商品专属死信交换机
     */
    @Bean
    public DirectExchange vipExpirationDLX() {
        return new DirectExchange(mqProperties.getVipExpirationDlx(), true, false);
    }

    /**
     * 商品专属死信队列
     */
    @Bean
    public Queue vipExpirationDLQ() {
        return new Queue(mqProperties.getVipExpirationDlq(), true);
    }

    /**
     * 绑定死信队列到死信交换机
     */
    @Bean
    public Binding vipExpirationDLBinding() {
        return BindingBuilder.bind(vipExpirationDLQ())
            .to(vipExpirationDLX())
            .with(mqProperties.getVipExpirationDlRoutingKey());
    }
}
